﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace KongZhiTaiTest
{

    /// <summary>
    /// 支付测试类
    /// </summary>
    public class PaymentShow
    {
        public const string _firstOrder = "001";
        public const string _secondOrder = "002";
        public const string _thirdOrder = "003";

        public static void Show(LockType lockType)
        {
            //测试相同订单
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("==========测试同一个订单=========");
            Console.ForegroundColor = ConsoleColor.White;
            OrderPay(_firstOrder, 1, lockType);
            OrderPay(_firstOrder, 2, lockType);
            OrderPay(_firstOrder, 3, lockType);
            Thread.Sleep(10000);
            //测试不同订单
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("=========测试不同订单===========");
            Console.ForegroundColor = ConsoleColor.White;
            OrderPay(_firstOrder, 1, lockType);
            OrderPay(_secondOrder, 2, lockType);
            OrderPay(_thirdOrder, 3, lockType);
        }

        /// <summary>
        /// 异步订单支付操作
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="threadNo"></param>
        /// <param name="lockType"></param>
        private static void OrderPay(string orderId,int threadNo,LockType lockType)
        {
            //new Thread(new ThreadStart(() => new Payment(orderId, threadNo).Pay(lockType)));
            new Thread(() => new Payment(orderId, threadNo).Pay(lockType)).Start();
            Thread.Sleep(10);
        }
    }

    /// <summary>
    /// 支付类
    /// </summary>
    public class Payment
    {
        //测试四种lock方式
        private readonly string _lockString;
        private readonly int _threadNo;
        private readonly object _lockObj = new object();
        private readonly static object _object = new object();

        public Payment (string orderId, int threadNo)
        {
            _lockString = orderId;
            _threadNo = threadNo;
        }

        /// <summary>
        /// 不同锁方式的支付环节
        /// </summary>
        /// <param name="type"></param>
        public void Pay(LockType type)
        {
            ShowMessage("等待锁资源...");
            switch (type)
            {
                case LockType.LockThis:
                    lock (this)
                    {
                        ShowAction();
                    }
                    break;
                case LockType.LockString:
                    lock (_lockString)
                    {
                        ShowAction();
                    }
                    break;
                case LockType.LockObject:
                    lock (_lockObj)
                    {
                        ShowAction();
                    }
                    break;
                case LockType.LockStaticObject:
                    lock (_object)
                    {
                        ShowAction();
                    }
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 封装一个虚拟支付的方法
        /// </summary>
        private void ShowAction()
        {
            ShowMessage(string.Format("进入锁并开始操作,开始时间：{0}",DateTime.Now.ToLongTimeString()));
            //耗时操作，消耗两秒钟
            Thread.Sleep(2000);
            ShowMessage(string.Format("操作完成,结束时间，{0}",DateTime.Now.ToLongTimeString()));
            ShowMessage("释放锁资源");
        }

        /// <summary>
        /// 封装一个打印输出的方法
        /// </summary>
        /// <param name="message"></param>
        private void ShowMessage(string message)
        {
            Console.WriteLine(string.Format("订单{0}的第{1}线程{2}",_lockString,_threadNo,message));
        }

    }

    /// <summary>
    /// 锁方式的枚举
    /// </summary>
    public enum LockType
    {
        LockThis = 0,
        LockString = 1,
        LockObject = 2,
        LockStaticObject = 3
    }


}
